import urllib2
import urllib
import os
import re
import sys
import threading
import ctypes
import mogUtil
from pydispatch import dispatcher
import configure
import wx


class PageProcess:

    def __init__(self, category, page, ringtongInfos, model):
        self._category = category
        self._page = page
        self._ringtongInfos = ringtongInfos
        self.downloadThread = None
        self.parseThread = None
        self.pattern = re.compile('-+')
        self.state = 0
        self._model = model
        dispatcher.connect(self.onPageParseComplite, signal='MSG_PARSE_COMPLITE')
        dispatcher.connect(self.onPageDone, 'MSG_PAGE_DONG')



    def reset(self, category, page, startId):
        self._page = page
        self._startId = startId
        self._category = category
        self.state = 0



    def onPageParseComplite(self, datalist):
        for data in datalist:
            curentId = self._startId + len(self._ringtongInfos)
            data['displayId'] = curentId
            filename = data['title'] + '-' + str(curentId)
            filename = filename.replace(' ', '-')
            filename = self.pattern.sub('-', filename)
            newfilename = re.sub('[/\\:*?"<>|.!+()~@$%#^*]', '', filename)
            data['filename'] = newfilename
            data['format'] = ''
            self._ringtongInfos.append(data)

        self.state = 1
        wx.CallAfter(dispatcher.send,'MSG_STATE_CHANGE', dispatcher.Anonymous, 2)
        wx.CallAfter(dispatcher.send,'MSG_RESET_GRID_VIEW')
        self.execute()



    def onPageDone(self):
        self.state = 2
        wx.CallAfter(dispatcher.send,'MSG_STATE_CHANGE', dispatcher.Anonymous, 4)
        self._model.nextStep()



    def stopThreads(self):
        if self.parseThread != None:
            self.parseThread.appExit = True
        if self.downloadThread != None:
            self.downloadThread.appExit = True



    def execute(self):
        if self.state == 0:
            self.parseThread = ParseThread(self._category, self._page)
            self.parseThread.setDaemon(True)
            self.parseThread.start()
            wx.CallAfter(dispatcher.send,'MSG_STATE_CHANGE', dispatcher.Anonymous, 1)
        elif self.state == 1:
            self.downloadThread = DownloadThread(self._ringtongInfos)
            self.downloadThread.setDaemon(True)
            self.downloadThread.start()
            wx.CallAfter(dispatcher.send,'MSG_STATE_CHANGE', dispatcher.Anonymous, 3)



    def isDone(self):
        return self.state == 2




class TagParseThread(threading.Thread):

    def __init__(self, ringtongInfos):
        threading.Thread.__init__(self)
        self._ringtongInfos = ringtongInfos
        self.appExit = False



    def run(self):
        try:
            dispatcher.send('MSG_STATE_CHANGE', dispatcher.Anonymous, 5)
            opener = urllib2.build_opener()
            opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3')]
            subRe = re.compile('<a\\s*href="/search/\\?skey=(.+?)">\\1</a>,?\\s+')
            for item in self._ringtongInfos:
                if item['tagParse'] == '0' and self.appExit == False:
                    tags = []
                    tagres = opener.open('http://' + configure.cfg['host'] + '/ringtone/' + item['id'], None, 45).read()
                    subMatch = subRe.search(tagres)
                    while subMatch != None:
                        tags.append(subMatch.group(1))
                        subMatch = subRe.search(tagres, subMatch.end(1))

                    item['tags'] = tags
                    item['tagParse'] = '1'
                    wx.CallAfter(dispatcher.send,'MSG_ITEM_TAG_PARSED')

            dispatcher.send('MSG_TAG_PARSE_COMPLITE')
        except urllib2.HTTPError as e:
            if self.appExit == False:
                dispatcher.send('MSG_NET_ERROR', dispatcher.Anonymous, -3)
        except urllib2.URLError as e:
            if self.appExit == False:
                dispatcher.send('MSG_NET_ERROR', dispatcher.Anonymous, -3)




class DownloadThread(threading.Thread):

    def __init__(self, ringtongInfos):
        threading.Thread.__init__(self)
        self._ringtongInfos = ringtongInfos
        self.appExit = False
        self.pattern = re.compile('filename=(.*?)\\.(.*?);\\s')
        self.filePattern = re.compile('\\.tmp$')



    def run(self):
        try:
            self.downloadFiles()
        except urllib2.HTTPError as e:
            if self.appExit == False:
                dispatcher.send('MSG_NET_ERROR', dispatcher.Anonymous, -2)
        except urllib2.URLError as e:
            if self.appExit == False:
                dispatcher.send('MSG_NET_ERROR', dispatcher.Anonymous, -2)
        except IOError as e:
            if self.appExit == False:
                dispatcher.send('MSG_NET_ERROR', dispatcher.Anonymous, -2)



    def downloadFile(self, item):
        url = 'http://' + configure.cfg['fileHost'] + '/file.php?fileID=' + item['id'] + '&type=ringt&ut_vid='
        filename = self.cur_file_dir() + os.sep + item['category'] + os.sep + item['filename'] + '.tmp'
        self.ensure_dir(filename)
        f = urllib.urlretrieve(url, filename)
        format = self.getFormat(f[1].headers)
        size = str(os.path.getsize(filename) / 1024 + 1) + 'kb'
        newfilename = self.filePattern.sub('.' + format, filename)
        if os.path.exists(newfilename):
            os.remove(newfilename)
        os.rename(filename, newfilename)
        item['filename'] = item['filename'] + '.' + format
        item['download'] = '1'
        item['format'] = format
        item['size'] = size



    def getFormat(self, headers):
        for x in headers:
            s = self.pattern.search(x)
            if s != None:
                return s.group(2)

        return 'unknow'



    def ensure_dir(self, f):
        d = os.path.dirname(f)
        if not os.path.exists(d):
            os.makedirs(d)



    def cur_file_dir(self):
        path = sys.path[0]
        if os.path.isdir(path):
            return path
        if os.path.isfile(path):
            return os.path.dirname(path)



    def downloadFiles(self):
        for item in self._ringtongInfos:
            if item['download'] == '0' and self.appExit == False:
                self.downloadFile(item)
                dispatcher.send('MSG_FILE_DOWNLOADED')

        dispatcher.send('MSG_PAGE_DONG')




class ParseThread(threading.Thread):

    def __init__(self, category, page):
        threading.Thread.__init__(self)
        self._category = category
        self._page = page
        self.appExit = False



    def run(self):
        try:
            self.parsePageInfo()
        except urllib2.HTTPError as e:
            if self.appExit == False:
                dispatcher.send('MSG_NET_ERROR', dispatcher.Anonymous, -1)
        except urllib2.URLError as e:
            if self.appExit == False:
                dispatcher.send('MSG_NET_ERROR', dispatcher.Anonymous, -1)



    def parsePageInfo(self):
        ringtongInfos = []
        source_encoding = 'iso-8859-1'
        path = '/ringtones/' + self._category + '/?&ord=added&ordt=asc'
        if self._page > 1:
            path += '&start=' + str((self._page - 1) * 30)
        opener = urllib2.build_opener()
        opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3')]
        url = 'http://' + configure.cfg['host'] + path
        print url
        f = opener.open(url, None, 45)
        res = f.readlines()
        p = re.compile('/ringtone/(\\d+)"><strong>(.+)</strong>(.*)</a></td>')
        for item in res:
            m = p.search(item)
            if m != None:
                id = m.group(1)
                orgTitle = mogUtil.unescape(m.group(3))
                orgTitle = mogUtil.unescape(orgTitle)
                orgTitle = orgTitle.decode('iso-8859-1').encode('utf-8')
                temp = unicode(orgTitle, 'ISO-8859-1', 'ignore')
                title = m.group(2).strip() + ' ' + temp.strip()
                title = mogUtil.removeAllSpecial(title)
                title = mogUtil.clearPunctuation(title)
                title = re.sub('^-\\s', '', title)
                title = re.sub('^null-\\s?-?\\s?', '', title)
                ringtongInfos.append({'id': id,
                 'category': self._category,
                 'title': title,
                 'tags': [],
                 'fileUrl': '/file.php?fileID=' + id + '&type=ringt',
                 'size': 0,
                 'download': '0',
                 'tagParse': '0'})

        dispatcher.send('MSG_PARSE_COMPLITE', dispatcher.Any, ringtongInfos)




